package com.wxhandle.cleandemo.api.controller;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.transaction.Transactional;

import com.wxhandle.cleandemo.application.dto.identity.SysClaimDto;
import com.wxhandle.cleandemo.application.dto.identity.SysClaimParam;
import com.wxhandle.cleandemo.application.dto.identity.SysServiceDto;
import com.wxhandle.cleandemo.application.dto.identity.VueMenuDto;
import com.wxhandle.cleandemo.core.domain.identity.SysClaim;
import com.wxhandle.cleandemo.core.domain.identity.SysService.ClaimType;
import com.wxhandle.cleandemo.core.services.SysClaimService;

import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;

@Api(tags="权限接口")
@RequiredArgsConstructor
@RestController
@RequestMapping("api/claim")
public class SysClaimController {
    @Autowired
    private WebApplicationContext applicationContext;

    private final SysClaimService service;
	private final ModelMapper modelMapper;

    @ApiOperation("查询权限列表")
    @GetMapping("list")
    public List<SysClaimDto> getList(@RequestParam SysClaimParam param){
        return service.getList(param).stream().map(claim-> modelMapper.map(claim, SysClaimDto.class))
        .collect(Collectors.toList());
    }
    @Async
    @ApiOperation("同步UI资源")
    @Transactional
    @PostMapping("menusync/{service}")
    public SysServiceDto syncVueMenu(@PathVariable("service") String service, @RequestBody List<VueMenuDto> menus){
        int i=0;
        SysServiceDto serviceDto = SysServiceDto.of(service, service, menus);
        List<SysClaimDto> claims= new ArrayList<>();
        for(VueMenuDto menu : menus) {
            if(!menu.getMeta().isHideInMenu())
                claims.add(SysClaimDto.of(menu, i++));
        }
        return serviceDto;
    }

    @Async
    @ApiOperation("同步权限列表")
    @GetMapping("permissionsync/{service}")
    @Transactional
    public Collection<SysClaimDto> refreshPermissions(@PathVariable("service") String service){

        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);

        // 拿到Handler适配器中的全部方法
        Map<RequestMappingInfo, HandlerMethod> methodMap = mapping.getHandlerMethods();
        Map<String, SysClaim> rootClaims = new HashMap<>();
        Map<String, List<SysClaim>> subClaims = new HashMap<>();

        for (RequestMappingInfo info : methodMap.keySet()){
            HandlerMethod method = methodMap.get(info);
            if(method.getBeanType().getPackageName().startsWith("com.wxhandle.cleandemo.api.controller")){


                String controller = method.getBean().toString().toLowerCase();
                controller = controller.substring(0, controller.length() - 10);
                ApiOperation operation = method.getMethodAnnotation(ApiOperation.class);
                String name = method.getMethod().getName();
                String desc = (null == operation) ? name : operation.value();

                // if(!rootClaims.containsKey(controller)) {
                //     Api api = method.getBeanType().getAnnotation(Api.class);

                //     rootClaims.put(controller, SysClaim.of(controller, (null == api) ? name : api.tags()[0], controller, rootClaims.size()));
                //     subClaims.put(controller, new ArrayList<>());
                // }
                // subClaims.get(controller).add(SysClaim.of(controller+"/"+name, desc, controller+"/"+name, subClaims.get(controller).size()));
            }
        }
        for(String key : rootClaims.keySet()){
            // SysClaim rootClaim = rootClaims.get(key);
            // rootClaim.setChildren(subClaims.get(key));
            // for(SysClaim subClaim : subClaims.get(key)){
            //     subClaim.setParent(rootClaim);
            //     // service.insert(subClaim);
            // }
            // service.insert(rootClaim);
        }

        return rootClaims.values().stream().map(c->modelMapper.map(c, SysClaimDto.class)).collect(Collectors.toList());
    }
}
